#coding:utf-8
'''
* coder  : Dzlua
* email  : 505544956@qq.com
* module : api-frame
* path   : app
* file   : mgr.py
* time   : 2017/10/19
'''
#--------------------#
import flask
import flask_script
import flask_restful
import flask_sqlalchemy
import flask_httpauth
import flask_migrate
#----------#
from flask_restful import reqparse
from flask import url_for, g, make_response, jsonify
from passlib.apps import custom_app_context as pwd_context
from itsdangerous import (TimedJSONWebSignatureSerializer
                          as Serializer, BadSignature, SignatureExpired)
#--------------------#

#----------------------------------------#
#--------------------#
def _config_app(app):
    try:
        import config
        app.config.from_object(config)
    except:
        pass
#--------------------#
#----------------------------------------#

#----------------------------------------#
#--------------------#
app = flask.Flask(__name__)
_config_app(app)
manager = flask_script.Manager(app)
db = flask_sqlalchemy.SQLAlchemy(app)
auth = flask_httpauth.HTTPBasicAuth()
migrate = flask_migrate.Migrate(app, db)
#--------------------#
#----------------------------------------#

#----------------------------------------#
#--------------------#
def Run():
    manager.run()
#--------------------#
#----------------------------------------#

#----------------------------------------#
#--------------------#
_blueprints = {}
#----------#
def _set_blueprint(name, blueprint):
    _blueprints[blueprint] = name
#----------#
def _get_blueprint(name):
    for bp in _blueprints:
        if _blueprints[bp] == name:
            return bp
    return None
#----------#
def _get_blueprint_name(blueprint):
    return _blueprints[blueprint]
#--------------------#

#--------------------#
_apis = {}
#----------#
def _set_api(name, api):
    _apis[api] = name
#----------#
def _get_api(name):
    for api in _apis:
        if _apis[api] == name:
            return api
    return None
#----------#
def _get_api_name(api):
    return _apis[api]
#--------------------#
#----------------------------------------#
    
#----------------------------------------#
#--------------------#
def create_blueprint(name):
    blueprint = flask.Blueprint(
        name,
        __name__,
        url_prefix='/' + name )
    #
    _set_blueprint(name, blueprint)
    return blueprint
#----------#
def register_blueprint(blueprint):
    app.register_blueprint(blueprint)
#----------#
def register_blueprint_by_name(name, bcreate=True):
    blueprint = get_blueprint(name, bcreate)
    register_blueprint(blueprint)
#----------#
def get_blueprint(name, bcreate=True):
    bp = _get_blueprint(name)
    if bp:
        return bp
    #
    if bcreate:
        return create_blueprint(name)
    return None
#--------------------#

#--------------------#
def craete_api_of_app():
    api = flask_restful.Api(app)
    _set_api('__app__', api)
    return api
#----------#
def get_api_of_app(bcreate=True):
    api = _get_api('__app__')
    if api:
        return api
    #
    if bcreate:
        return craete_api_of_app()
    return None
#----------#
def create_api(blueprint, api_name=None):
    api = flask_restful.Api(blueprint)
    _set_api(api_name or _get_blueprint_name(blueprint), api)
    return api
#----------#
def create_api_by_name(blueprint_name, api_name=None):
    bp = get_blueprint(blueprint_name)
    api = flask_restful.Api(bp)
    _set_api(api_name or blueprint_name, api)
    return api
#----------#
def get_api(name, blueprint_name=None, bcreate=True):
    api = _get_api(name)
    if api:
        return api
    #
    if bcreate:
        return create_api_by_name(blueprint_name or name, name)
    return None    
#----------#
def add_api(api, resource, *urls, **kwargs):
    try:
        endpoint = resource.endpoint
    except:
        endpoint = resource.__name__.lower()
    api.add_resource(resource, endpoint=endpoint, *urls, **kwargs)
#--------------------#
#----------------------------------------#

#----------------------------------------#
#--------------------#
class ApiBase(flask_restful.Resource):
    #----------#
    def reqparse(self):
        try:
            return self._reqparse
        except:
            self._reqparse = reqparse.RequestParser()
        return self._reqparse
    #----------#
    def add_arg(self, *args, **kwargs):
        self.reqparse().add_argument(*args, **kwargs)
    #----------#
    def args(self):
        try:
            return self._args
        except:
            self._args = self.reqparse().parse_args()
        return self._args
    #----------#
    def arg(self, name, default_value=None):
        return self.args().get(name) or default_value
#----------#
class ApiAuthBase(ApiBase):
    decorators = [auth.login_required]
#--------------------#
#----------------------------------------#

#----------------------------------------#
#--------------------#
def hash(password):
    return pwd_context.encrypt(password)
#----------#
def verify(password, hash_password):
    return pwd_context.verify(password, hash_password)
#--------------------#
#----------------------------------------#
